import React, { useContext, useState } from 'react';
import {
  Card,
  Row,
  Col,
  Slider,
  Button,
  Checkbox,
  message,
  Typography,
  Popconfirm,
  Tooltip,
} from 'antd';
import { SerialContext } from '../context/SerialContext';
import { ReadService } from '../services/ReadService';
import { WriteService } from '../services/WriteService';
import { SerialServoService } from '../services/SerialServoService';
import { handleUpError } from '../utils/errorHandler';
import {
  AlarmLEDConfig,
  AlarmLEDLabels,
  AlarmShutdownLabels,
  AlarmShutdownConfig,
  combineLedSettings,
  combineShutdownSettings,
  parseAngleFromBytes,
  parseLedSettings,
  parseShutdownSettings,
  parseVoltage,
} from '../utils/conversion';
import { EEPromParam, EEPromParamWrite } from '../models/up_request';
import './ServoLimitationComponent.css';
import { InfoCircleOutlined } from '@ant-design/icons';
import CardTitleWithTip from '../views/CardTitleWithTip';

const { Text, Paragraph } = Typography;

const chunkArray = <T,>(arr: T[], size: number): T[][] => {
  const result: T[][] = [];
  for (let i = 0; i < arr.length; i += size) {
    result.push(arr.slice(i, i + size));
  }
  return result;
};

const TabServoLimitation: React.FC = () => {
  const ctx = useContext(SerialContext);
  if (!ctx) return null;
  const { serialState, globalModel, servoModel } = ctx;

  const [angleMin, setAngleMin] = useState(0);
  const [angleMax, setAngleMax] = useState(300);
  const [voltMin, setVoltMin] = useState(6);
  const [voltMax, setVoltMax] = useState(19);
  const [torque, setTorque] = useState(300);
  const allLEDs = Object.values(AlarmLEDConfig).filter(
    (v): v is AlarmLEDConfig => typeof v === 'number'
  );
  const allShutdowns = Object.values(AlarmShutdownConfig).filter(
    (v): v is AlarmShutdownConfig => typeof v === 'number'
  );
  const [ledErrors, setLedErrors] = useState<AlarmLEDConfig[]>(allLEDs);
  const [shutdownErrors, setShutdownErrors] =
    useState<AlarmShutdownConfig[]>(allShutdowns);

  const [loading, setLoading] = useState({
    angle: false,
    volt: false,
    torque: false,
    led: false,
    shutdown: false,
    restoring: false,
  });

  const checkOpen = () => {
    if (!serialState.isSerialOpen || !globalModel.global_serial_id) {
      message.error('请先打开串口并选择串口设备');
      return false;
    }
    return true;
  };

  const wrapAction = async (
    key: keyof typeof loading,
    action: () => Promise<void>
  ) => {
    setLoading((prev) => ({ ...prev, [key]: true }));
    try {
      await action();
    } finally {
      setLoading((prev) => ({ ...prev, [key]: false }));
    }
  };

  const requestAngle = () =>
    wrapAction('angle', async () => {
      if (!checkOpen()) return;
      const data = await ReadService.read4ByteEEProm(
        globalModel.global_serial_id,
        servoModel.servo_id,
        EEPromParam.GetAngleLimit
      );
      const min = parseAngleFromBytes(data[0], data[1]);
      const max = parseAngleFromBytes(data[2], data[3]);
      setAngleMin(min);
      setAngleMax(max);
      message.success(`角度范围：${min}° ~ ${max}°`);
    });

  const saveAngle = () =>
    wrapAction('angle', async () => {
      if (!checkOpen()) return;
      await SerialServoService.sendAngleLimit(
        globalModel.global_serial_id,
        servoModel.servo_id,
        angleMin,
        angleMax
      );
      message.success('保存角度限制成功');
    });

  const requestVoltage = () =>
    wrapAction('volt', async () => {
      if (!checkOpen()) return;
      const data = await ReadService.readRangeEEProm(
        globalModel.global_serial_id,
        servoModel.servo_id,
        EEPromParam.GetVoltageRange
      );
      const min = parseVoltage(data[0]);
      const max = parseVoltage(data[1]);
      setVoltMin(min);
      setVoltMax(max);
      message.success(`电压范围：${min}V ~ ${max}V`);
    });

  const saveVoltage = () =>
    wrapAction('volt', async () => {
      if (!checkOpen()) return;
      await SerialServoService.sendVoltageLimit(
        globalModel.global_serial_id,
        servoModel.servo_id,
        voltMin,
        voltMax
      );
      message.success('保存电压限制成功');
    });

  const requestTorque = () =>
    wrapAction('torque', async () => {
      if (!checkOpen()) return;
      const data = await ReadService.readRangeEEProm(
        globalModel.global_serial_id,
        servoModel.servo_id,
        EEPromParam.GetMaxTorque
      );
      const parsed = parseAngleFromBytes(data[0], data[1]);
      setTorque(parsed);
      message.success(`最大扭矩：${parsed}`);
    });

  const saveTorque = () =>
    wrapAction('torque', async () => {
      if (!checkOpen()) return;
      await WriteService.writeEEProm(
        globalModel.global_serial_id,
        servoModel.servo_id,
        EEPromParamWrite.SetMaxTorque,
        torque
      );
      message.success('保存扭矩成功');
    });

  const requestLed = () =>
    wrapAction('led', async () => {
      if (!checkOpen()) return;
      const data = await ReadService.readSingleEEProm(
        globalModel.global_serial_id,
        servoModel.servo_id,
        EEPromParam.GetAlarmLED
      );
      setLedErrors(parseLedSettings(data));
      message.success('LED 设置读取成功');
    });

  const saveLed = () =>
    wrapAction('led', async () => {
      if (!checkOpen()) return;
      const byte = combineLedSettings(ledErrors);
      await WriteService.writeEEProm(
        globalModel.global_serial_id,
        servoModel.servo_id,
        EEPromParamWrite.SetAlarmLED,
        byte
      );
      message.success(`LED 保存成功（配置字节 ${byte}）`);
    });

  const requestShutdown = () =>
    wrapAction('shutdown', async () => {
      if (!checkOpen()) return;
      const data = await ReadService.readSingleEEProm(
        globalModel.global_serial_id,
        servoModel.servo_id,
        EEPromParam.GetAlarmShutdown
      );
      setShutdownErrors(parseShutdownSettings(data));
      message.success('卸载保护读取成功');
    });

  const saveShutdown = () =>
    wrapAction('shutdown', async () => {
      if (!checkOpen()) return;
      const byte = combineShutdownSettings(shutdownErrors);
      await WriteService.writeEEProm(
        globalModel.global_serial_id,
        servoModel.servo_id,
        EEPromParamWrite.SetAlarmShutdown,
        byte
      );
      message.success(`卸载保护保存成功（字节 ${byte}）`);
    });

  const restoreDefaults = () =>
    wrapAction('restoring', async () => {
      if (!checkOpen()) return;
      await SerialServoService.restore(
        globalModel.global_serial_id,
        servoModel.servo_id
      );
      setAngleMin(0);
      setAngleMax(300);
      setVoltMin(6);
      setVoltMax(19);
      setTorque(300);
      setLedErrors(allLEDs);
      setShutdownErrors(allShutdowns);
      message.success('已恢复默认设置');
    });

  return (
    <div className="limit-settings">
      <Card
        title={
          <CardTitleWithTip
            title="角度限制 (0–300°)"
            tip="设置舵机可旋转的最小与最大角度"
          />
        }
        className="section-card"
        extra={
          <>
            <Button
              size="small"
              onClick={requestAngle}
              loading={loading.angle}
              style={{ marginRight: 6 }}
            >
              查询
            </Button>
            <Button size="small" onClick={saveAngle} loading={loading.angle}>
              保存
            </Button>
          </>
        }
      >
        <Row gutter={8} align="middle">
          <Col flex="auto">
            <Slider min={0} max={300} value={angleMin} onChange={setAngleMin} />
          </Col>
          <Col>
            <Text>最小角度: {angleMin}°</Text>
          </Col>
        </Row>
        <Row gutter={8} align="middle" style={{ marginTop: 8 }}>
          <Col flex="auto">
            <Slider min={0} max={300} value={angleMax} onChange={setAngleMax} />
          </Col>
          <Col>
            <Text>最大角度: {angleMax}°</Text>
          </Col>
        </Row>
      </Card>

      <Card
        title={
          <CardTitleWithTip
            title="电压限制 (6–19V)"
            tip="设置供电电压允许的范围，防止过压/欠压损坏"
          />
        }
        className="section-card"
        extra={
          <>
            <Button
              size="small"
              onClick={requestVoltage}
              loading={loading.volt}
              style={{ marginRight: 6 }}
            >
              查询
            </Button>
            <Button size="small" onClick={saveVoltage} loading={loading.volt}>
              保存
            </Button>
          </>
        }
      >
        <Row gutter={8} align="middle">
          <Col flex="auto">
            <Slider min={6} max={19} value={voltMin} onChange={setVoltMin} />
          </Col>
          <Col>
            <Text>最小电压: {voltMin}V</Text>
          </Col>
        </Row>
        <Row gutter={8} align="middle" style={{ marginTop: 8 }}>
          <Col flex="auto">
            <Slider min={6} max={19} value={voltMax} onChange={setVoltMax} />
          </Col>
          <Col>
            <Text>最大电压: {voltMax}V</Text>
          </Col>
        </Row>
      </Card>

      <Card
        title={
          <CardTitleWithTip title="最大扭矩限制" tip="设置舵机的最大输出力矩" />
        }
        className="section-card"
        extra={
          <>
            <Button
              size="small"
              onClick={requestTorque}
              loading={loading.torque}
              style={{ marginRight: 6 }}
            >
              查询
            </Button>
            <Button size="small" onClick={saveTorque} loading={loading.torque}>
              保存
            </Button>
          </>
        }
      >
        <Row gutter={8} align="middle">
          <Col flex="auto">
            <Slider min={0} max={300} value={torque} onChange={setTorque} />
          </Col>
          <Col>
            <Text>当前扭矩: {torque}</Text>
          </Col>
        </Row>
      </Card>

      <Card
        title={
          <CardTitleWithTip
            title="LED 错误提示设置"
            tip="发生错误时是否通过 LED 指示提示"
          />
        }
        className="section-card"
        extra={
          <>
            <Button
              size="small"
              onClick={requestLed}
              loading={loading.led}
              style={{ marginRight: 6 }}
            >
              查询
            </Button>
            <Button size="small" onClick={saveLed} loading={loading.led}>
              保存
            </Button>
          </>
        }
      >
        <Row gutter={8}>
          {chunkArray(allLEDs, 4).map((group, i) => (
            <Col span={12} key={i}>
              <Checkbox.Group
                options={group.map((e) => ({
                  label: AlarmLEDLabels[e],
                  value: e,
                }))}
                value={ledErrors}
                onChange={(v) => setLedErrors(v as AlarmLEDConfig[])}
              />
            </Col>
          ))}
        </Row>
      </Card>

      <Card
        className="section-card"
        title={
          <CardTitleWithTip
            title="卸载保护设置"
            tip="发生错误时是否自动关闭输出以保护舵机"
          />
        }
        extra={
          <>
            <Button
              size="small"
              onClick={requestShutdown}
              loading={loading.shutdown}
              style={{ marginRight: 6 }}
            >
              查询
            </Button>
            <Button
              size="small"
              onClick={saveShutdown}
              loading={loading.shutdown}
            >
              保存
            </Button>
          </>
        }
      >
        <Row gutter={8}>
          {chunkArray(allShutdowns, 4).map((group, i) => (
            <Col span={12} key={i}>
              <Checkbox.Group
                options={group.map((e) => ({
                  label: AlarmShutdownLabels[e],
                  value: e,
                }))}
                value={shutdownErrors}
                onChange={(v) => setShutdownErrors(v as AlarmShutdownConfig[])}
              />
            </Col>
          ))}
        </Row>
      </Card>

      <div style={{ textAlign: 'center', marginTop: 24 }}>
        <Popconfirm
          title="确定要恢复默认设置？所有当前设置将被重置。"
          onConfirm={restoreDefaults}
          okText="确定"
          cancelText="取消"
        >
          <Button type="primary" danger loading={loading.restoring}>
            恢复默认
          </Button>
        </Popconfirm>
      </div>
    </div>
  );
};

export default TabServoLimitation;
